home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / System / Capture ƒ / Capture.c next >
Encoding:
C/C++ Source or Header  |  1990-02-12  |  21.9 KB  |  797 lines  |  [TEXT/KAHL]

  1. /* Capture program - example of serial port control
  2. *
  3. *  File:  Capture.c
  4. *
  5. *  Programmer:        James R. Logan Jr.
  6. *  Organization:    Brigham Young University
  7. *  Email:        loganj@byuvax.bitnet
  8. *             loganj@yvax.byu.edu
  9. *  Phone:        (801) 378-3617
  10. *
  11. *   Captures incoming data from the active serial port and
  12. *   displays visible characters via a TextEdit record.
  13. *   Provides control of serial port characteristics (baud 
  14. *   rate, parity, stop bits, handshaking ... ).
  15. *
  16. *   If you convert this program to interact with real time 
  17. *   data obtained through the serial port then you should  
  18. *   remove the call to "TEKey()" below (because it's slow) 
  19. *   and add your own code at that point to process incoming 
  20. *   data.
  21. *
  22. *   Version 1.1 improvement:
  23. *
  24. *   When data is being captured to a file it is not displayed 
  25. *   on the screen, but the mouse cursor flickers between the 
  26. *   arrow and watch cursors to indicate that data is being 
  27. *   received.
  28. *
  29. *  TBD:  Incoming text is never removed from the TextEdit 
  30. *        record, so eventually the program will run out 
  31. *        of memory.
  32. *
  33. *        The use of TextEdit for display purposes is very 
  34. *        slow, and causes the processing of serial port 
  35. *        traffic to be slow.
  36. *
  37. *        Menus should be done by "MENU" resource.
  38. *
  39. *        The cursor should only flicker when the application 
  40. *        window is front most.  As it is now, the cursor may 
  41. *        continue to flicker even if another application owns 
  42. *        the front most window.
  43. *
  44. *        The intent here is not to be a "terminal emulator"
  45. *        so the "insertion point" doesn't blink, the "delete"
  46. *        and "backspace" keys don't work, and the "copy, cut, 
  47. *        and paste" functions don't work.
  48. */
  49.  
  50. #include <Quickdraw.h>
  51. #include <WindowMgr.h>
  52. #include <SerialDvr.h>
  53. #include <MenuMgr.h>
  54. #include <EventMgr.h>
  55. #include <TextEdit.h>
  56. #include <DialogMgr.h>
  57. #include <ControlMgr.h>
  58. #include <FontMgr.h>
  59. #include "StdFilePkg.h"
  60. #include <stdio.h>
  61.  
  62. #include "ToolboxUtil.h"
  63.  
  64. #include "Capture.h"
  65.  
  66. #define lastmenu 4
  67. #define applemenu 1
  68. #define filemenu 256
  69. #define editmenu 257
  70. #define settingsmenu 258
  71.  
  72. #define input_size 2048
  73.  
  74. CursHandle watch;    /* cursors */
  75.  
  76. static ResType
  77.   creator = 'EDIT',
  78.   driver = 'DRVR',
  79.   filetype = 'TEXT',  
  80.   Setres = 'CNFG',
  81.   texttype = 'TEXT';
  82.  
  83. static char   *minputnam[]     = {"\p.ain","\p.bin"};
  84. static char   *moutputnam[] = {"\p.aout","\p.bout"};
  85.  
  86. static char  *mbtext[] = {
  87.       "\p300 baud","\p600 baud","\p1200 baud","\p1800 baud","\p2400 baud",
  88.     "\p3600 baud","\p4800 baud","\p7200 baud","\p9600 baud",
  89.     "\p19200 baud","\p57600 baud", 0};
  90. static char  *mdtext[] = {"\p5 data bits","\p6 data bits","\p7 data bits","\p8 data bits", 0};
  91. static char  *mptext[] = {"\pNo parity","\pOdd parity","\pEven parity", 0};
  92. static char  *mstext[] = {"\p1 stop bit","\p1.5 stop bits","\p2 stop bits", 0};
  93. static char  *mPorttext[] = {"\pModem Port","\pPrinter Port", 0};
  94. static char  *mprottext[] = {"\pNo handshaking","\pXon/Xoff Handshaking", 0};
  95.  
  96. static int  mbtable[]     = 
  97.   { baud300, baud600,
  98.     baud1200,baud1800,
  99.     baud2400,baud3600,
  100.     baud4800,baud7200,
  101.     baud9600,baud19200,baud57600};
  102.  
  103. static int  mdtable[]     = {data5,data6,data7,data8};
  104. static int  mptable[]     = {noParity,oddParity,evenParity};
  105. static int  mstable[]     = {stop10,stop15,stop20};
  106. static int  minputnum[] = {-6,-8};    /* File numbers of incoming modem/printer ports */
  107. static int  moutputnum[] = {-7,-9};    /* File numbers of outgoing modem/printer ports */
  108. static int  mramnum[]     = {sPortA, sPortB};
  109.  
  110. SerShk shakies = 
  111.   { (char)0,
  112.     (char)0,
  113.     (char)17,    /* "xon" character is control q */
  114.     (char)19,    /* "xoff" character is control s */
  115.     (char)0,
  116.     (char)0,
  117.     (char)1,    /* "fInX" field: enable incoming "xon/xoff" handshaking */
  118.     (char)0};
  119.  
  120. Boolean capturing,doneflag;
  121. EventRecord myevent;
  122. MenuHandle mymenus[lastmenu+1];
  123. WindowPtr
  124.   whichwindow,  /* Working variable to test which window is the frontmost */
  125.   noticeWindow; /* Window for copyright notice */
  126.  
  127. WindowRecord
  128.   nrecord;    /* Window record for copyright notice */
  129.  
  130. int
  131.   capturefile,    /* Capture incoming data to file, file id */
  132.   mpi,        /* Modem input file refnum         */
  133.   mpo,        /* Modem output file refnum         */
  134.   mbaud,        /* Port speed         */
  135.   mdata,        /* Port data bits     */
  136.   mparity,      /* Port parity         */
  137.   mport,        /* Port selected     */
  138.   mprot,        /* Port protocol     */
  139.   mstop;        /* Port stop bits     */
  140.  
  141. Rect     dragRect;    /* used by DragWindow(...)    */
  142.  
  143. char *modembuf,*incoming;
  144. Str255 EnterOutputFilename_TempBuf; 
  145.  
  146.  
  147. /* Set up the menu bar (TBD: do it with resources) */
  148.  
  149. setupmenus() {
  150. int i;
  151. Str255 appletitle;
  152.   InitMenus();
  153.   appletitle[0] = 1; appletitle[1] = 20;
  154.   mymenus[1] = NewMenu(applemenu, appletitle);
  155.   AppendMenu(mymenus[1], "\pAbout Capture…;(-");
  156.   AddResMenu(mymenus[1], driver);
  157.   mymenus[2] = NewMenu(filemenu, "\pFile");
  158.   AppendMenu(mymenus[2], "\pCapture to file…;Save as…;Save Settings;Quit");
  159.   mymenus[3] = NewMenu(editmenu, "\pEdit");
  160.   AppendMenu(mymenus[3], "\pCopy;Cut;Paste;Clear");
  161.   mymenus[4] = NewMenu(settingsmenu, "\pSettings");
  162.   AppendMenu(mymenus[4], "\pModem");
  163.   for (i=1; i<=lastmenu; i++) InsertMenu(mymenus[i], 0);
  164.   DrawMenuBar();
  165. }
  166.  
  167.  
  168. /* Process menu items */
  169.  
  170. docommand(g,themenu,theitem) screen *g; int themenu, theitem; {
  171. /* This procedure processes all actions initiated by mouse down events on 
  172.    items of menus in the menu bar. */
  173. char name[256];
  174. int i,refnum;
  175.   switch (themenu) {
  176.   case applemenu:
  177.     if (theitem == 1) { /* About Capture */
  178.       DoAbout(g);
  179.     } else if (theitem > 2) {
  180.       GetItem(mymenus[1], theitem, &name);
  181.       refnum = OpenDeskAcc(name);
  182.     }
  183.     break;
  184.   case filemenu:
  185.     switch (theitem) {
  186.       case 1:
  187.         if (capturing) {
  188.           CloseCaptureFile(g);
  189.           capturing = FALSE;
  190.         } else {
  191.           CaptureToFile(g);
  192.           capturing = TRUE;
  193.         }
  194.         CheckItem( mymenus[2], 1, capturing);
  195.         break;
  196.       case 2: 
  197.         SaveToFile(g);
  198.         break;
  199.       case 3: 
  200.         saveSettings(g);
  201.         break;
  202.       case 4: 
  203.         doneflag = TRUE; 
  204.         break;
  205.     }
  206.     break;
  207.   case editmenu:
  208.     if (!SystemEdit(theitem-1)) {
  209.       switch (theitem) {
  210.       case 1: break;
  211.       case 2: break;
  212.       case 3: break;
  213.       case 4: 
  214.         clearrem(g);
  215.         break;
  216.     } }
  217.     break;
  218.   case settingsmenu:
  219.     switch (theitem) {
  220.       case 1: 
  221.         Setmodem();
  222.         break;
  223.     }
  224.     break;
  225.   }
  226.   HiliteMenu(0);
  227. }
  228.  
  229.  
  230. /* Get the (program settings) "CNFG" resource */
  231.  
  232. getSettings(g) screen *g; {
  233. char **myResource; int i,*resptr;
  234. #define    SettingsID    31324
  235.  
  236.     myResource = GetResource( Setres, SettingsID);
  237.     resptr = (int*) *myResource;
  238.     SetSettings(g,resptr);
  239.       ReleaseResource(myResource);
  240. }
  241.  
  242.  
  243. /* Set the program settings from the "CNFG" resource */
  244.  
  245. SetSettings(g,rp) screen *g; int *rp; {
  246. int i,*resptr;
  247.   resptr = rp;
  248.   mbaud     = *(resptr++);
  249.   mdata     = *(resptr++);
  250.   mparity     = *(resptr++);
  251.   mport     = *(resptr++);
  252.   mprot     = *(resptr++);
  253.   mstop     = *(resptr++);
  254.   for (i = 0; i < maxwinpars; i++) {
  255.     g->Windowsize[i] = *(resptr++);
  256.   }
  257. }
  258.  
  259.  
  260. /* Save the program settings in the "CNFG" resource */
  261.  
  262. saveSettings(g)  screen *g; {
  263. Point     myPoint;
  264. int     i,*resptr;
  265. char     **myResource; 
  266. GrafPtr tempPort;
  267.  
  268.   GetPort(&tempPort);
  269.   myResource = GetResource( Setres, SettingsID);
  270.   resptr = (int*) *myResource;
  271.   *(resptr++) = mbaud;
  272.   *(resptr++) = mdata;
  273.   *(resptr++) = mparity;
  274.   *(resptr++) = mport;
  275.   *(resptr++) = mprot;
  276.   *(resptr++) = mstop;
  277.   
  278.   g->Windowsize[0] = 0;        /* Not used */
  279.   g->Windowsize[1] = 0;        /* Not used */
  280.  
  281. /* First window */
  282.   myPoint = topLeft(  g->storyWindow->portRect);
  283.   SetPort(g->storyWindow); LocalToGlobal(&myPoint);
  284.   g->Windowsize[2] = myPoint.h;
  285.   g->Windowsize[3] = myPoint.v;
  286.   g->Windowsize[4] = g->storyWindow->portRect.right;
  287.   g->Windowsize[5] = g->storyWindow->portRect.bottom;
  288.  
  289. /* Second window */
  290.   g->Windowsize[6] = 0;        /* Not used */
  291.   g->Windowsize[7] = 0;        /* Not used */
  292.   g->Windowsize[8] = 0;        /* Not used */
  293.   g->Windowsize[9] = 0;        /* Not used */
  294.   
  295.   for (i = 0; i < maxwinpars; i++)
  296.     *(resptr++) = g->Windowsize[i];
  297.            
  298.   ChangedResource(myResource);
  299.   WriteResource(myResource);
  300.   ReleaseResource(myResource);
  301.   SetPort(tempPort);
  302. }
  303.  
  304.  
  305. /* Open a serial port, use the "incoming" buffer, and 
  306.    set "xon/xoff" handshaking on */
  307.  
  308. PortOpen() {
  309. int fstatus,mSettings;
  310.   fstatus = RAMSDOpen(mramnum[mport]);
  311.   fstatus = FSOpen( minputnam[mport],  minputnum[mport],&mpi);
  312.   fstatus = FSOpen( moutputnam[mport], moutputnum[mport],&mpo);
  313.  
  314.   mSettings = mbtable[mbaud] + mdtable[mdata] + mptable[mparity] + mstable[mstop];
  315.   SerReset(mpi,mSettings);
  316.   SerReset(mpo,mSettings);
  317.   SerSetBuf(mpi,incoming,input_size);    /* Input buffer specification */
  318.   shakies.fInX = (char) mprot;
  319.   SerHShake(mpi,&shakies);        /* Handshake parameters */
  320. }
  321.  
  322.  
  323. /* Close the serial port */
  324.  
  325. PortClose() {
  326. int fstatus;
  327.   RAMSDClose(mramnum[mport]);
  328.   if (mpi != NULL) { 
  329.     fstatus = FSClose(mpi); 
  330.     mpi = NULL; 
  331.     unlink(minputnam[mport]);
  332.   }
  333.   if (mpo != NULL) { 
  334.     fstatus = FSClose(mpo); 
  335.     mpo = NULL; 
  336.     unlink(moutputnam[mport]); 
  337.   } 
  338. }
  339.  
  340.  
  341. CloseCaptureFile(g) screen *g; {
  342. int fstatus;
  343.   fstatus = FSClose(capturefile); 
  344. }
  345.  
  346.  
  347. /* Write the incoming data to a file */
  348.  
  349. CaptureToFile(g) screen *g; {
  350. int fstatus;
  351. long fcount,mysize;
  352. Point     pt; 
  353. SFReply reply; 
  354. Str255     origname;
  355.  
  356.   SetPt(&pt, 198, 40);
  357.   strcpy( origname, "\p");
  358.   SFPutFile( pt, EnterOutputFilename_TempBuf, origname, NULL, &reply);
  359.   if (reply.good) {
  360.     fstatus = Create(reply.fName,reply.vRefNum,creator,filetype);
  361.     fstatus = FSOpen(reply.fName,reply.vRefNum,&capturefile);
  362. } }
  363.  
  364.  
  365. /* Write the contents of the TextEdit record to a file */
  366.  
  367. SaveToFile(g) screen *g; {
  368. int fp,fstatus;
  369. long fcount,mysize;
  370. Point     pt; 
  371. SFReply reply; 
  372. Str255     origname;
  373.  
  374.   mysize = GetHandleSize((*g->storyth)->hText);
  375.   if (mysize > 0L) {
  376.     SetPt(&pt, 198, 40);
  377.     strcpy( origname, "\p");
  378.     SFPutFile( pt, EnterOutputFilename_TempBuf, origname, NULL, &reply);
  379.     if (reply.good) {
  380.       fstatus = Create(reply.fName,reply.vRefNum,creator,filetype);
  381.       fstatus = FSOpen(reply.fName,reply.vRefNum,&fp);
  382.       HLock((*g->storyth)->hText);
  383.       fcount = mysize;
  384.       fstatus = FSWrite(fp,&fcount,*(*g->storyth)->hText);
  385.       HUnlock((*g->storyth)->hText);
  386.       fstatus = FSClose(fp); 
  387.   } }
  388. }
  389.  
  390.  
  391. /* This function checks to see if there is any data coming into 
  392.    the serial port, and if so captures the data. */
  393.  
  394. DoModem(g,modembuf) screen *g; char *modembuf; {
  395. register int mycount1,mycount2;
  396. OSErr     mpistatus;    /* mpi is modem.port.in    */
  397. long    fcount,mpicount,mx;
  398. int    fstatus;
  399. unsigned char c;
  400.  
  401.   mpistatus = SerGetBuf(mpi,&mpicount);        /* How much data is coming? */
  402.   if (mpicount > 0) {                /* Number of characters. */
  403.  
  404.     if (capturing)
  405.       SetCursor(*watch);
  406.  
  407.     fcount = mpicount;
  408.     fstatus = FSRead(mpi,&fcount,modembuf);    /* Read all of the data. */
  409.  
  410. /* If capturing to file then don't display on screen */
  411.  
  412.     if (capturing) {
  413.  
  414.       mycount2 = 0;
  415.       for (mycount1 = 0; mycount1 < fcount; mycount1++) { /* Remove line feeds */
  416.         if (modembuf[mycount1] != 10)
  417.           modembuf[mycount2++] = modembuf[mycount1];
  418.       }
  419.       fcount = mycount2;
  420.       fstatus = FSWrite(capturefile,&fcount,modembuf);
  421.       InitCursor();
  422.  
  423. /* Display the data into the serial port window. */
  424.     } else {
  425.       for (mx = 0; mx < mpicount; mx++) {        /* For each character received...*/
  426.         c = modembuf[mx];
  427.         if ((c > 31) || (c == 13) || (c == 8))    /* Only characters that are visible */
  428.  
  429. /* It would speed things up a lot if we didn't use 
  430.    TEKey here and put the data directly into the 
  431.    TextEdit record.  Or, better yet, don't use 
  432.    TextEdit at all. */
  433.  
  434.           TEKey(modembuf[mx],g->storyth);    /* Put each character in the window */
  435.       }
  436.  
  437. /* Scroll the window so that the insertion point is visible */
  438.       ShowSelect(g->storyWindow,g->storybar,g->storyth);
  439. } } }
  440.  
  441.  
  442. /* Paint a wide border around button #1 to indicate which 
  443.    button is the default button */
  444.  
  445. PaintDial(myDialog)     /* Circle OK    item 1    */
  446. DialogPtr myDialog; {
  447. int     item_type;
  448. Handle     item_Handle;  
  449. Rect     item_box; 
  450.  
  451.   SetPort(    myDialog);
  452.   GetDItem(    myDialog,1,&item_type,&item_Handle,&item_box);
  453.   item_box.left--; item_box.top--;    /* TBD:  use InsetRect() */
  454.   item_box.right++; item_box.bottom++;
  455.   PenSize(3,3);
  456.   InsetRect(      &item_box,-3,-3);
  457.   FrameRoundRect( &item_box,16,16);
  458. }
  459.  
  460.  
  461. /* GetDIHandle - return handle value of dialog item */
  462.  
  463. Handle GetDIHandle(theDia,i) DialogPtr theDia;int i; {
  464. int theType;
  465. Handle theHandle;
  466. Rect theRect;
  467.   GetDItem(theDia, i, &theType, &theHandle, &theRect);
  468.   return theHandle;
  469. }
  470.  
  471.  
  472. /* Restrict the value of an integer to between "lo" and "hi" */
  473.  
  474. int BoundsLimitWithWrapAround( vPtr, lo, hi) int *vPtr, lo, hi; {
  475.   if( *vPtr < lo) *vPtr = hi;
  476.   else if( *vPtr > hi) *vPtr = lo;
  477.   return( *vPtr);
  478. }
  479.  
  480.  
  481. /* Set the characteristics of the serial port */
  482.  
  483. Setmodem() {
  484. GrafPtr     tempPort;
  485. int     the_item,item_type,mSettings,tbaud,tdata,tparity,tport,tprot,tstop;
  486. Handle     item_Handle;  
  487. Rect     item_box; 
  488. char     item_text[256];  
  489. DialogPtr myDialog;  
  490.  
  491.   InitCursor();  
  492.   GetPort(&tempPort);
  493. #define MODEM_DLOD_ID    28243
  494.  
  495.   myDialog = GetNewDialog( MODEM_DLOD_ID,(DialogPeek) 0L, (WindowPtr)-1L);  
  496.   PaintDial(myDialog);    /* OK    */
  497.   SetIText( GetDIHandle( myDialog, 15), (Str255 *) mbtext[mbaud]);  
  498.   SetIText( GetDIHandle( myDialog, 16), (Str255 *) mdtext[mdata]);  
  499.   SetIText( GetDIHandle( myDialog, 17), (Str255 *) mptext[mparity]);  
  500.   SetIText( GetDIHandle( myDialog, 18), (Str255 *) mstext[mstop]);
  501.   SetIText( GetDIHandle( myDialog, 19), (Str255 *) mPorttext[mport]);
  502.   SetIText( GetDIHandle( myDialog, 20), (Str255 *) mprottext[mprot]);
  503.     /* set dlog temps    */
  504.   tbaud = mbaud; tdata = mdata; tparity = mparity; 
  505.   tport = mport; tprot = mprot; tstop = mstop;
  506.   
  507.   do { 
  508.     ModalDialog((long) 0,&the_item); 
  509.     if ((the_item == 3) || (the_item == 4) )     /* UP/DOWN     tbaud    */
  510.     { 
  511.       tbaud += ((the_item == 3 /* UP*/) ? 1 : -1);
  512.  
  513.       BoundsLimitWithWrapAround( &tbaud, 0, 10);
  514.       SetIText( GetDIHandle( myDialog, 15),  (Str255 *) mbtext[tbaud]);  
  515.     } 
  516.     else if ((the_item == 5) || (the_item == 6)) /* UP/DOWN tdata    */
  517.     { 
  518.       tdata += ((the_item == 5 /* UP*/) ? 1 : -1);
  519.       
  520.       BoundsLimitWithWrapAround( &tdata, 0, 3);
  521.       SetIText( GetDIHandle( myDialog, 16), (Str255 *) mdtext[tdata]);  
  522.     }
  523.     else if ((the_item == 7) || (the_item == 8)) /* UP/DOWN tparity    */
  524.     { 
  525.       tparity += ((the_item == 7 /* UP*/) ? 1 : -1);
  526.       BoundsLimitWithWrapAround( &tparity, 0, 2);
  527.       SetIText( GetDIHandle( myDialog, 17), (Str255 *) mptext[tparity]);  
  528.     } 
  529.     else if ((the_item == 9) || (the_item == 10)) /* UP/DOWN tstop    */
  530.     { 
  531.       tstop += ((the_item == 9 /* UP*/) ? 1 : -1);
  532.       BoundsLimitWithWrapAround( &tstop, 0, 2);
  533.       SetIText( GetDIHandle( myDialog, 18), (Str255 *) mstext[ tstop]);  
  534.     }
  535.     else if ((the_item == 11) || (the_item == 12)) /* UP/DOWN tpORt    */
  536.     { 
  537.       tport += ((the_item == 11 /* UP*/) ? 1 : -1);
  538.       BoundsLimitWithWrapAround( &tport, 0, 1);
  539.       SetIText( GetDIHandle( myDialog, 19), (Str255 *) mPorttext[ tport]);  
  540.     }
  541.      else if ((the_item == 13) || (the_item == 14)) /* UP/DOWN tpROt    */
  542.     { 
  543.       tprot += ((the_item == 13 /* UP*/) ? 1 : -1);
  544.       BoundsLimitWithWrapAround( &tprot, 0, 1);
  545.       SetIText( GetDIHandle( myDialog, 20), (Str255 *) mprottext[ tprot]);  
  546.     }
  547.   } while ((the_item != OK) && (the_item != Cancel));
  548.   
  549.   if (the_item == OK)     /* save temps to theRealThings    */
  550.   {
  551.     PortClose();
  552.     mbaud = tbaud; mdata = tdata; mparity = tparity; 
  553.     mport = tport; mprot = tprot; mstop = tstop;
  554.     PortOpen();
  555.   }
  556.   CloseDialog( myDialog); 
  557.   SetPort(tempPort);
  558.   return( the_item);
  559. }
  560.  
  561.  
  562. /* Update the TextEdit record in an active window */
  563.  
  564. updatestory (g) screen *g; {
  565. Rect mybox;
  566.   BeginUpdate(g->storyWindow); 
  567.   SetPort(g->storyWindow);
  568.   mybox = g->storyWindow->portRect;
  569.   mybox.left = mybox.right - 15;
  570.   ClipRect(&mybox);
  571.   DrawGrowIcon(g->storyWindow);
  572.   ClipRect(&g->storyWindow->portRect);
  573.   DrawControls(g->storyWindow);
  574.   mybox = (*g->storyth)->destRect;
  575.   mybox.bottom = 32767;
  576.   TEUpdate(&mybox,g->storyth);
  577.   EndUpdate(g->storyWindow);
  578. }
  579.  
  580. /* Interface with the operator */
  581.  
  582. main() {
  583. unsigned char c;       /* Keyboard character */
  584. Boolean 
  585.   commandkey,
  586.   extendtext,
  587.   returnkey,
  588.   temp;       /* Receives value from GetNextEvent - ignored */
  589. int 
  590.   fp,
  591.   fstatus,
  592.   windowcode, /* The value indicates what object the mouse button was pointing to when pressed */
  593.   theItem,
  594.   theMenu;
  595. long 
  596.   fcount,
  597.   theCommand;
  598. Point 
  599.   dragpoint,
  600.   mypoint;
  601. DialogPtr whichdialog;
  602. Rect windowrect;
  603.  
  604. long bit,hexvalue,hexout,myerror,mysize,offset;
  605. GrafPtr tempPort;
  606. int i,item_type,the_item;
  607. Handle item_Handle,myhandle;  
  608. Rect mybox,screenRect; 
  609. screen *g;
  610. Str255 tbuf,txtbuf,mpobuf;
  611.  
  612.  
  613.   InitGraf( (Ptr) &thePort);
  614.   InitFonts();
  615.   FlushEvents( everyEvent, 0);
  616.   InitWindows();
  617.   TEInit();
  618.   InitDialogs( 0L);    /* "0L" should be the restart proc address */
  619.   setupmenus();
  620.   InitCursor();
  621.  
  622.   GetPort(&tempPort);
  623.   InitCursor();
  624.   watch = GetCursor(watchCursor);
  625.  
  626.   capturing = FALSE;
  627.  
  628.   mysize = sizeof(screen);
  629.   g = (screen*) NewPtr(mysize);
  630.  
  631.   mysize = 65536L;
  632.   modembuf = NewPtr(mysize);
  633.   incoming = NewPtr(mysize);
  634.  
  635.   getSettings(g);    /* Get default settings from "CNFG" resource */
  636.   PortOpen();        /* Open the serial port */
  637.  
  638. /* Create the copyright notice window */
  639.  
  640.   SetRect(&screenRect,30,40,290,292);
  641.   noticeWindow = NewWindow(&nrecord,&screenRect,"\p",FALSE,3,(long)-1L,0,(long)0L);
  642.  
  643. /* Create the display window */
  644.  
  645.   SetRect( &screenRect, 
  646.     g->Windowsize[2],  g->Windowsize[3], 
  647.     g->Windowsize[2] + g->Windowsize[4], 
  648.     g->Windowsize[3] + g->Windowsize[5]);
  649.       
  650.   g->storyWindow = NewWindow(&g->storyrecord, &screenRect, 
  651.      "\pSerial Port" ,     /* WTitle */
  652.      FALSE,        /* Visible */ 
  653.      0, 
  654.      (long)-1, 
  655.      TRUE        /* GoAway */, 
  656.      (long)0);
  657.   SetRect( &screenRect, 
  658.     g->Windowsize[4] - 15, 0, g->Windowsize[4], g->Windowsize[5] - 13);
  659.   g->storybar = NewControl( g->storyWindow, 
  660.     &screenRect, "\p", FALSE, 0, 0, 0, scrollBarProc, 0L);
  661.   SetPort(g->storyWindow);
  662.  
  663.   TextSize(9); TextMode( srcCopy); TextFont( geneva);
  664.   SetRect( &screenRect, 4, 12, g->Windowsize[4] - 15, g->Windowsize[5]);
  665.   g->storyth = TENew( &screenRect,&screenRect);
  666.   FixStoryWindow(g,FALSE,g->Windowsize[5],g->Windowsize[4]);
  667.  
  668.   SetRect(&dragRect,0,0,32767,32767);    /* TBD set to screenSize */
  669.  
  670. /* This is the main event loop, which scans for input from the modem 
  671.    and from the keyboard. */
  672.    
  673.   do {
  674.     commandkey = FALSE;
  675.     returnkey = FALSE;
  676.     SystemTask();  /* Process desk accessories and other system stuff */
  677.     temp = GetNextEvent(everyEvent, &myevent);             /* Get the next event */
  678.     mypoint = myevent.where;                               /* Save the event mouse position */
  679.     windowcode = FindWindow(myevent.where, &whichwindow);  /* Save the event window info */
  680.  
  681. /* Call a function to capture the data from the serial port. */
  682.     DoModem(g,modembuf);
  683.  
  684. /* Process all events */
  685.     switch (myevent.what) {
  686.     case mouseDown:
  687.  
  688.       switch (windowcode) {
  689.  
  690. /* Process menu bar events here */
  691.       case inMenuBar: 
  692.         theCommand = MenuSelect(&myevent.where);
  693.     theMenu = HiWord( theCommand);
  694.     theItem = LoWord( theCommand);
  695.     docommand(g,theMenu, theItem);
  696.         break;
  697.  
  698. /* Process events for desk accessories here */
  699.       case inSysWindow: SystemClick(&myevent, whichwindow); break;
  700.       case inDrag: 
  701.     DragWindow( whichwindow, myevent.where, &dragRect);
  702.         break;
  703.       case inGrow: 
  704.     {    
  705.           long tPtlong;
  706.           Point growPoint;
  707.     
  708.           SetRect(&mybox,187,187,32767,32767);
  709.  
  710.           tPtlong =  GrowWindow( whichwindow, myevent.where, &mybox);
  711.           growPoint.h = LoWord( tPtlong);
  712.           growPoint.v = HiWord( tPtlong);
  713.       
  714.           if (tPtlong != 0 ) {        /* TBD DO_IT_RIGHT */
  715.         if (whichwindow == g->storyWindow) 
  716.               FixStoryWindow(g,FALSE,growPoint.v,growPoint.h);
  717.           }
  718.         }
  719.         break;
  720.       case inContent: 
  721.         if (whichwindow == g->storyWindow) {
  722.           SetPort(whichwindow);
  723.           GlobalToLocal(&myevent.where);
  724.           if ( PtInRect( myevent.where, &(*g->storyth)->viewRect)) {
  725.             if ((myevent.modifiers & shiftKey) == 0) 
  726.               extendtext = FALSE; 
  727.             else
  728.               extendtext = TRUE; 
  729.           
  730.             TEClick( myevent.where, extendtext,g->storyth);
  731.           } else myControls(g,whichwindow,g->storyth,&myevent.where);
  732.         }
  733.         break;
  734.       case inGoAway: break;
  735.       }
  736.       break;
  737.     case mouseUp: 
  738.       switch (windowcode) {
  739.       case inMenuBar: break;
  740.       case inSysWindow: break;
  741.       case inGrow: break;
  742.  
  743. /* Process mouseup events that occur in the main font window if the letter 
  744.    dialogue window is not visible. */
  745.       case inContent: break;
  746.       case inGoAway: break;
  747.       }
  748.       break;
  749.  
  750. /* Process Control key characters from the keyboard */
  751.     case keyDown:
  752.     case autoKey: 
  753.  
  754. /* Clear the notice window whenever a key is pressed. */
  755.       c = (char) (255 & myevent.message);
  756.       if ((myevent.modifiers & cmdKey) != 0) {
  757.         commandkey = TRUE;
  758.  
  759. /* If the key is visible then send it out the serial port. */
  760.       } else if ((c > 31) || (c == 13) || (c == 8) || (c == 3)) {
  761.         fcount = 1; 
  762.         fstatus = FSWrite(mpo,&fcount,&c);
  763.  
  764. /* If the key is not visible (unknown) then display it's value. */
  765.       } else {
  766.         sprintf(modembuf,"Key: %d\r",c);
  767.         i = 0;
  768.         while (modembuf[i] != 0) {
  769.           TEKey(modembuf[i++],g->storyth);
  770.       } }
  771.       break;
  772.  
  773.     case activateEvt: 
  774.       if (whichwindow == g->storyWindow) {
  775.     SetPort(g->storyWindow);
  776.     mybox = g->storyWindow->portRect;
  777.     mybox.left = mybox.right - 16;
  778.     InvalRect(&mybox);
  779.     if ((myevent.modifiers & 1) != 0) 
  780.           ShowControl(g->storybar);
  781.         else     
  782.           HideControl(g->storybar); 
  783.      }
  784.       break;
  785.  
  786. /* Update the display of the indicated application window.  These update 
  787.    events occur whenever the letter dialogue appears or disappears and 
  788.    when desk accessories are moved around on the screen. */
  789.     case updateEvt: 
  790.       if (myevent.message == (long) g->storyWindow) updatestory(g);
  791.       break;
  792.     }
  793.  
  794.   } while (doneflag == 0);
  795.   SetPort(tempPort);
  796. }
  797.